"""
文件备份工具
实现文件的复制、备份和版本管理 
"""
import os
import shutil
import datetime
import zipfile

def ensure_directory_exists(directory):
    """确保目录存在"""
    if not os.path.exists(directory):
        os.makedirs(directory)
        print(f"创建目录: {directory}")

def backup_file(source_path, backup_dir="backups"):
    """备份单个文件"""
    ensure_directory_exists(backup_dir)
    
    if not os.path.isfile(source_path):
        print(f"错误: {source_path} 不是文件或不存在")
        return False
    
    try:
        # 生成备份文件名（添加时间戳）
        filename = os.path.basename(source_path)
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_filename = f"{os.path.splitext(filename)[0]}_{timestamp}{os.path.splitext(filename)[1]}"
        backup_path = os.path.join(backup_dir, backup_filename)
        
        # 复制文件
        shutil.copy2(source_path, backup_path)
        print(f"文件备份成功: {backup_path}")
        return True
        
    except Exception as e:
        print(f"备份失败: {e}")
        return False

def backup_directory(source_dir, backup_dir="backups"):
    """备份整个目录"""
    ensure_directory_exists(backup_dir)
    
    if not os.path.isdir(source_dir):
        print(f"错误: {source_dir} 不是目录或不存在")
        return False
    
    try:
        # 生成备份文件名
        dirname = os.path.basename(source_dir.rstrip('/\\'))
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        zip_filename = f"{dirname}_{timestamp}.zip"
        zip_path = os.path.join(backup_dir, zip_filename)
        
        # 创建zip备份
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(source_dir):
                for file in files:
                    file_path = os.path.join(root, file)
                    # 在zip文件中保持相对路径
                    arcname = os.path.relpath(file_path, os.path.dirname(source_dir))
                    zipf.write(file_path, arcname)
        
        print(f"目录备份成功: {zip_path}")
        return True
        
    except Exception as e:
        print(f"目录备份失败: {e}")
        return False

def list_backups(backup_dir="backups"):
    """列出所有备份文件"""
    if not os.path.exists(backup_dir) or not os.listdir(backup_dir):
        print("暂无备份文件")
        return
    
    print("\n=== 备份文件列表 ===")
    backups = sorted(os.listdir(backup_dir))
    for i, backup in enumerate(backups, 1):
        backup_path = os.path.join(backup_dir, backup)
        size = os.path.getsize(backup_path)
        mod_time = datetime.datetime.fromtimestamp(os.path.getmtime(backup_path))
        
        print(f"{i}. {backup}")
        print(f"   大小: {size} 字节, 修改时间: {mod_time}")

def restore_backup(backup_name, target_path, backup_dir="backups"):
    """从备份恢复文件"""
    backup_path = os.path.join(backup_dir, backup_name)
    
    if not os.path.exists(backup_path):
        print(f"备份文件不存在: {backup_name}")
        return False
    
    try:
        if backup_path.endswith('.zip'):
            # 解压zip备份
            with zipfile.ZipFile(backup_path, 'r') as zipf:
                zipf.extractall(target_path)
            print(f"从 {backup_name} 恢复目录到 {target_path}")
        else:
            # 复制单个文件
            shutil.copy2(backup_path, target_path)
            print(f"从 {backup_name} 恢复文件到 {target_path}")
        
        return True
        
    except Exception as e:
        print(f"恢复失败: {e}")
        return False

def main():
    backup_dir = "backups"
    
    while True:
        print("\n=== 文件备份工具 ===")
        print("1. 备份单个文件")
        print("2. 备份整个目录")
        print("3. 查看备份列表")
        print("4. 从备份恢复")
        print("5. 退出")
        
        choice = input("请选择操作 (1-5): ")
        
        if choice == '1':
            file_path = input("请输入要备份的文件路径: ")
            backup_file(file_path, backup_dir)
            
        elif choice == '2':
            dir_path = input("请输入要备份的目录路径: ")
            backup_directory(dir_path, backup_dir)
            
        elif choice == '3':
            list_backups(backup_dir)
            
        elif choice == '4':
            backup_name = input("请输入备份文件名: ")
            target_path = input("请输入恢复目标路径: ")
            restore_backup(backup_name, target_path, backup_dir)
            
        elif choice == '5':
            print("感谢使用文件备份工具！")
            break
            
        else:
            print("无效选择，请重新输入！")

if __name__ == "__main__":
    main()